import grails.testing.mixin.integration.Integration
import grails.testing.spock.OnceBefore
import io.micronaut.http.HttpRequest
import io.micronaut.http.HttpResponse
import io.micronaut.http.HttpStatus
import io.micronaut.http.MediaType
import io.micronaut.http.client.HttpClient
import org.grails.web.json.JSONObject
import spock.lang.Shared
import spock.lang.Specification

@Integration
class OAuth2JwtTokenSpec extends Specification {

    static final clientId = "app1serv"
    static final clientSecret = "secret"
    static final username = "openid123456"
    static final password = "device-1234567890"

    @Shared
    HttpClient client

    @OnceBefore
    void init() {
        String baseUrl = "http://localhost:$serverPort"
        this.client = HttpClient.create(baseUrl.toURL())
    }

//    void "测试grant_type是authorize的令牌申请"() {
//        when: "使用默认的认证数据申请令牌"
//        HttpResponse<JSONObject> resp = client.toBlocking().exchange(
//                HttpRequest.POST("/oauth/authorize", ["grant_type": "authorization_code", username: username, password: password])
//                        .accept(MediaType.APPLICATION_JSON_TYPE)
//                        .basicAuth(clientId, clientSecret)
//                        .contentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE),
//                JSONObject)
//
//        then: "检查申请接口的响应结果"
//        resp.status == HttpStatus.OK
//        resp.body.isPresent()
//    }

    void "测试grant_type是password和refresh_token的令牌申请"() {
        when: "使用默认的认证数据申请令牌"
        HttpResponse<JSONObject> resp1 = client.toBlocking().exchange(
                HttpRequest.POST("/oauth/token", ["grant_type": "password", username: username, password: password])
                        .accept(MediaType.APPLICATION_JSON_TYPE)
                        .basicAuth(clientId, clientSecret)
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE),
                JSONObject)

        then: "检查申请接口的响应结果"
        resp1.status == HttpStatus.OK
        resp1.body.isPresent()

        and: "从接口响应结果中获取jwt令牌并验证"
        def jwt = resp1.body()
        jwt.containsKey("access_token")
        jwt.containsKey("refresh_token")
        jwt.containsKey("jti")
        jwt.get("token_type") == "bearer"
        (1..1800).contains(jwt.get("expires_in"))

        when: "使用刷新令牌申请新的访问令牌"
        HttpResponse<JSONObject> resp2 = client.toBlocking().exchange(
                HttpRequest.POST("/oauth/token", ["grant_type": "refresh_token", refresh_token: jwt.get("refresh_token")])
                        .accept(MediaType.APPLICATION_JSON_TYPE)
                        .basicAuth(clientId, clientSecret)
                        .contentType(MediaType.APPLICATION_FORM_URLENCODED_TYPE),
                JSONObject)

        then: "检查申请接口的响应结果"
        resp2.status == HttpStatus.OK
        resp2.body.isPresent()

        and: "获取新的访问令牌并验证"
        def jwt2 = resp2.body()
        jwt2.get("access_token") != jwt.get("access_token")
        (1..1800).contains(jwt2.get("expires_in"))
    }
}
